﻿using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;

namespace Anno
{
    public static class PathUtil
    {
        public static dynamic MatchPathParams(string path, string pathPattern)
        {
            IsMatch(path, pathPattern, out dynamic pathParams);

            return pathParams;
        }

        private static bool IsMatch(string path, string pathPattern, out dynamic pathParams)
        {
            if (path == null || pathPattern == null)
            {
                throw new ArgumentNullException();
            }

            pathParams = new ExpandoObject();

            if (path.Trim('/').Equals(pathPattern.Trim('/'), StringComparison.CurrentCultureIgnoreCase))
            {
                return true;
            }
            if (pathPattern.Trim('/').StartsWith(path.Trim('/') + "?", StringComparison.InvariantCultureIgnoreCase))
            {
                return true;
            }
            //if (path.Trim('/').StartsWith(pathPattern.Trim('/'), StringComparison.InvariantCultureIgnoreCase))
            //{
            //    return true;
            //}

            var pathArray = path.Trim('/').Split('/');
            var patternArray = pathPattern.Trim('/').Split('/');

            if (pathArray.Length != patternArray.Length)
            {
                return false;
            }

            var isMatch = true;
            var paramsDict = new Dictionary<string, string>();
            for (int i = 0; i < pathArray.Length; i++)
            {
                var pathNode = pathArray[i].Trim();
                var patternNode = patternArray[i].Trim();

                if (pathNode.Equals(patternNode, StringComparison.CurrentCultureIgnoreCase))
                {
                    continue;
                }
                if (patternNode.StartsWith("{") && patternNode.EndsWith("}"))
                {
                    var paramName = patternNode.Substring(1, patternNode.Length - 2);
                    if (!paramsDict.ContainsKey(paramName))
                    {
                        paramsDict.Add(paramName, pathNode);
                    }
                    continue;
                }
                if (patternNode.StartsWith(":"))
                {
                    var paramName = patternNode.Substring(1, patternNode.Length - 1);
                    if (!paramsDict.ContainsKey(paramName))
                    {
                        paramsDict.Add(paramName, pathNode);
                    }
                    continue;
                }

                isMatch = false;
            }

            pathParams = paramsDict.ToDynamic();
            return isMatch;
        }

        public static bool IsMatch(string path, string pathPattern)
        {
            return IsMatch(path.TrimEnd('/').TrimStart('/'), pathPattern.TrimEnd('/').TrimStart('/'), out dynamic pathParams);
        }

        public static string GetBaseRoute(string template, string controllerName)
        {
            var baseRoute = "";
            var rt = "controller";
            //if (template?.ToLower().Contains("[controller]") ==true)
            //{
            //    //if (template.IndexOf('[') >= 0)
            //    //    baseRoute = $"{template.Substring(0, template.IndexOf('[')).TrimEnd('/').TrimStart('/')}";

            //    //var rgx = new System.Text.RegularExpressions.Regex(@"(?i)(?<=\[)(.*)(?=\])");//中括号[]
            //    //rt = rgx.Match(template).Value;//中括号[]
            //    rt = "controller";
            //    baseRoute += $"/{controllerName.Substring(0, controllerName.ToLower().IndexOf(rt))}/";
            //}
            //else 
            if (template.Length > 0 && template.IndexOf('[') < 0)
            {
                baseRoute = $"{template.TrimEnd('/').TrimStart('/')}";
            }
            else
            {
                baseRoute += $"/{controllerName.Substring(0, controllerName.ToLower().IndexOf(rt))}/";
            }
            baseRoute = $"/{baseRoute.TrimEnd('/').TrimStart('/')}/";

            return baseRoute;
        }

        #region GetServerByHash
        /// <summary>
        /// 负载均衡算法--源哈希法（Hash）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="serverList"></param>
        /// <param name="source"></param>
        /// <returns></returns>
        public static T GetServerByHash<T>(this IEnumerable<T> serverList, object source)
        {
            if (serverList.IsNullOrEmpty_())
            {
                return default(T);
            }
            if (serverList.Count() == 1)
            {
                return serverList.ElementAt(0);
            }
            if (source == null) source = serverList;
            var hs = Math.Abs(source.GetHashCode());
            var index = hs % serverList.Count();
            return serverList.ElementAt(index);
        }
        #endregion
    }
}
